import React, { Component } from 'react';
import DomHelper from '../domHelper';
import LoaderHelper from './loaderHelper';
import { StereoHelper, MeshHelper } from '../../stereoHelper';
import { THREED, THREED_TYPES } from '../../../../../../utils/consts';
import tool from '../../../../../../utils/tool';
import ThreedHelper from '../../../../../../utils/ThreedHelper';

class ThreedLoader extends Component {
    constructor(props) {
        super(props);
        this.state = {
            widget: props.widget
        }
        this.resetWidget = this.resetWidget.bind(this);
        this.updateThreed = this.updateThreed.bind(this);
    }

    componentWillMount() {
        const { queryThreedState, resources } = this.props;

        this.threedState = resources[this.state.widget.md5] && resources[this.state.widget.md5].state;
        this.threedState = this.threedState === undefined ? 0 : this.threedState;
        ThreedHelper.inject ({
            consts: THREED,
            state: this.threedState,
            resetWidget: this.resetWidget,
            requestState: queryThreedState,
        });
    }

    componentDidMount() {
        if (this.state.widget.action && this.state.widget.action.fbx_js_url) {
            this.specifyThreedLoader(this.state.widget);
        } else {
            this.threedGeometryLoader(this.state.widget);
        }
    }

    componentWillReceiveProps(nextProps) {

        if (nextProps.resources !== this.props.resources) {
            // state => data
            let threedStateObj = nextProps.resources[nextProps.widget.md5];
            let threedState = threedStateObj && threedStateObj.state;
            threedState = threedState === undefined ? 0 : threedState;
            if (threedState !== this.threedState) {
                this.threedState = threedState;
                ThreedHelper.inject ({
                    state: threedState
                });
            }
            if (threedState == 1) {
                let widgetWidthNewState = ThreedHelper.updateThreed(nextProps.widget.id, threedStateObj);
                this.resetWidget(widgetWidthNewState);
            }
        }
    }

    componentWillUnmount() {
        this.resetWidget = function(){};
        ThreedHelper.inject ({
            resetWidget: this.resetWidget
        });
    }

    /**
     * 3D模型加载器
     */
    specifyThreedLoader(data) {
        let that = this;
        let loader = new THREE.SceneLoader();
        loader.load(data.action.fbx_js_url, function(result) {
            // 加载特定模型
            if (result &&
                result.scene &&
                result.scene.children &&
                result.scene.children.length === 2) {
                let mesh = result.scene.children[1];
                // 如果是Object3D则尝试转换为Mesh
                if (mesh.type === THREED.MESH_TYPE.OBJECT3D) {
                    mesh = that.createMeshBySceneData(result, data);
                    if (mesh.type === THREED.MESH_TYPE.MESH) {
                        DomHelper.scene.add(mesh);
                        that.threedMeshCreateFinish(data);
                    } else {
                        that.threedGeometryLoader(data);
                    }
                } else if (mesh.type === THREED.MESH_TYPE.MESH) {
                    mesh = that.meshCreator(mesh, THREE.PlaneGeometry, {}, data);
                    DomHelper.scene.add(mesh);
                    that.threedMeshCreateFinish(data);
                } else {
                    that.threedGeometryLoader(data);
                }
            } else {
                // 数据解析失败则直接加载2d模型
                that.threedGeometryLoader(data);
            }
            // loading in progress
        }, function() {
            // loading failed
        }, function() {
            // 数据加载失败则直接加载2d模型
            that.threedGeometryLoader(data);
        });
    }

    createMeshBySceneData(data, widget) {
        let geometries = data.geometries,
            materials = data.materials;
        if ((geometries && !tool.isEmptyObject(geometries)) &&
            (materials && !tool.isEmptyObject(materials))) {
            let geometry = tool.getItemByObjectDataOfType(geometries, THREE.Geometry);
            let material = tool.getItemByObjectDataOfType(materials, THREE.MeshBasicMaterial);
            if (geometry && material) {
                return LoaderHelper.meshCreator(null, THREE.PlaneGeometry, {}, widget, geometry, material);
            }
        }
        return null;
    }

    threedMeshCreateFinish(data) {
        // 3D模型创建完毕后才判断模型状态，防止未创建完成就触发
        return ThreedHelper.judge(data);
    }

    /**
     * 3D模型2D样式加载器
     */
    threedGeometryLoader(data) {
        let that = this;
        LoaderHelper.specifyImageLoader(data, function() {
            that.threedMeshCreator.call(that, this, data);
        });
    }

    threedMeshCreator(image, data) {
        let width = data.width + data.stateWidth,
            height = data.height;

        let imgFn = function(canvas) {
            let ctx = canvas.getContext("2d");
            ctx.drawImage(image, data.imgPosX, data.imgPosY, data.imgWidth, data.imgHeight);
        };

        let textFn = function(canvas) {
            let ctx = canvas.getContext("2d");
            ctx.fillStyle = data.stateColor;
            ctx.font = data.textSize + "px Arial";

            if (data.msg1) {
                ctx.fillText(data.msg1, data.text1PosX, data.text1PosY);
            }

            if (data.msg2) {
                ctx.fillText(data.msg2, data.text2PosX, data.text2PosY);
            }
        };

        let gradColor = tool.converionColor(data.color);
        let canvas = LoaderHelper.canvasCreator({
            data: data,
            imgFn: imgFn,
            textFn: textFn,
            gradientWidth: 45,
            gradientHeight: 45,
            containerWidth: width,
            containerHeight: height,
            gradientParam: gradColor
        });
        let texture = new THREE.CanvasTexture(canvas);
        let geometry = new THREE.PlaneGeometry(width, height);
        let material = new THREE.MeshBasicMaterial({ map: texture, side: THREE.DoubleSide, transparent: true, opacity: data.opacity });

        let mesh = MeshHelper.getMeshById(data.id);
        if (mesh) {
            mesh.material = material;
        } else {
            mesh = LoaderHelper.meshCreator(null, THREE.PlaneGeometry, {}, data, geometry, material);
            DomHelper.scene.add(mesh);
            this.threedMeshCreateFinish(data);
        }
    }

    resetWidget(newWidget) {
        this.setState({
            widget: newWidget
        }, function(){
            LoaderHelper.resetMeshItem(this.state.widget, this.updateThreed);
        });
    }

    updateThreed(data) {
        var that = this;
        LoaderHelper.specifyImageLoader(data, function (){
            that.threedMeshCreator.call(that, this, data);
        });
    } 

    render() {
        return (<div />)
    }
}

export default ThreedLoader;
